// src/hooks/useList.ts
import { onMounted, ref, unref, watch, computed } from "vue";
import { ElMessage } from "element-plus"; // 导入 ElMessage 用于错误提示

const DEFAULT_MESSAGE: MessageType = {
  GET_DATA_IF_FAILED: "获取列表数据失败",
  EXPORT_DATA_IF_FAILED: "导出数据失败"
};

// 假设 T 是 listRequestFn 返回的 data.list 中的单个项的类型
export default function useList<T = any, K extends object = Record<string, any>>( // T 用于列表项类型，K 用于筛选条件类型
  listRequestFn: (params: { page: number; page_size: number } & K) => Promise<ResponseDataType<{ list: T[]; total: number }>>,
  options: OptionsType<T, K> = {}
) {
  const {
    immediate = true, // 是否立即请求
    preRequest,
    message = DEFAULT_MESSAGE,
    filterOption = ref({}) as Ref<K>, // 确保 filterOption 默认是一个Ref的空对象
    exportRequestFn = undefined, // 导出数据函数
    transformFn = undefined, // 对返回数据进行处理
    pageSizes = [10, 30, 60, 100]
  } = options;
  const { GET_DATA_IF_FAILED, EXPORT_DATA_IF_FAILED } = message;

  // 加载态
  const loading = ref(false);
  // 当前页
  const curPage = ref(1);
  // 总数
  const total = ref(0);
  // 分页大小
  const pageSize = ref(pageSizes[0] || 10); // 初始pageSize使用pageSizes的第一个值
  // 数据
  const list = ref<T[]>([]);

  const loadData = async (page = curPage.value, size = pageSize.value) => {
    // 兼容page可能是event
    const requestPage = typeof page === "object" ? unref(curPage) : page;

    loading.value = true;
    try {
      preRequest?.();
      const params = {
        page: requestPage,
        page_size: size,
        ...unref(filterOption) // 确保解构 Ref 的值
      };
      const result = await listRequestFn(params); // listRequestFn的参数类型现在更明确

      let transformedData: ListReturn<T>;

      if (transformFn) {
        // 如果提供了 transformFn，则使用它处理原始响应
        transformedData = transformFn(result);
      } else {
        // 否则，直接从 result.data 中提取 list 和 total
        if (!result.data || !Array.isArray(result.data.list) || typeof result.data.total === "undefined") {
          throw new Error("API返回数据格式不符合预期: data.list或data.total缺失");
        }
        transformedData = {
          list: result.data.list,
          total: result.data.total
        };
      }

      list.value = transformedData.list;
      total.value = transformedData.total;

      options?.requestSuccess?.(transformedData); // 传递处理后的数据
      return {
        list: transformedData.list,
        total: transformedData.total
      };
    } catch (error) {
      if (GET_DATA_IF_FAILED) {
        ElMessage.error(GET_DATA_IF_FAILED); // 使用 ElMessage 提示
        console.error(GET_DATA_IF_FAILED, error); // 打印详细错误
      }
      options?.requestError?.(error);
      return { list: [], total: 0 }; // 失败时返回空数据
    } finally {
      loading.value = false;
    }
  };

  // 定义一个重置函数
  const reset = () => {
    // 确保 filterOption.value 是一个对象才能遍历
    if (filterOption.value && typeof filterOption.value === "object") {
      const keys = Reflect.ownKeys(filterOption.value);
      keys.forEach(key => {
        // 将筛选条件重置为 undefined 或其默认值
        Reflect.set(filterOption.value, key, undefined); // 假设 undefined 表示空
      });
    }
    curPage.value = 1; // 重置页码
    pageSize.value = pageSizes[0] || 10; // 重置每页大小
    loadData(); // 重新加载数据
  };

  // 定义一个异步函数exportFile，用于导出文件
  const exportFile = async () => {
    if (!exportRequestFn) {
      // 简化检查
      ElMessage.error("当前没有提供导出数据函数");
      throw new Error("当前没有提供exportRequest函数");
    }
    try {
      loading.value = true; // 导出也应该有加载态
      const {
        data: { link }
      } = await exportRequestFn(unref(filterOption)); // 确保解构 Ref 的值
      window.open(link);
      options?.exportSuccess?.();
      if (message.EXPORT_DATA_IF_SUCCEED) {
        ElMessage.success(message.EXPORT_DATA_IF_SUCCEED);
      }
    } catch (error) {
      if (EXPORT_DATA_IF_FAILED) {
        ElMessage.error(EXPORT_DATA_IF_FAILED);
        console.error(EXPORT_DATA_IF_FAILED, error);
      }
      options?.exportError?.(error);
    } finally {
      loading.value = false;
    }
  };

  // 返回一个带有 computed 的对象
  const pagination = computed(() => ({
    total: total.value,
    pageSize: pageSize.value,
    currentPage: curPage.value, // Element Plus Pagination 使用 'current-page'
    pageSizes: pageSizes
  }));

  // 监听分页数据改变
  // 只有当 curPage 或 pageSize 改变时才触发 loadData
  // watch([curPage, pageSize], () => {
  //     loadData(); // 不传参，使用 ref 的最新值
  // });

  onMounted(() => {
    if (immediate) {
      loadData(); // 初始加载
    }
  });

  return {
    loading,
    list,
    filterOption, // 筛选条件对象
    reset, // 重置筛选条件和分页
    exportFile, // 导出文件
    loadData, // 手动加载数据（例如在搜索按钮点击时）

    // 暴露分页相关的响应式数据和处理函数
    curPage, // 直接暴露 curPage
    pageSize, // 直接暴露 pageSize
    total, // 直接暴露 total
    pagination, // 计算属性，方便绑定到 ElPagination
    handleCurrentChange: (page: number) => {
      curPage.value = page;
      loadData();
    }, // ElPagination 的 @current-change
    handleSizeChange: (size: number) => {
      pageSize.value = size;
      loadData();
    } // ElPagination 的 @size-change
  };
}

// Api接口类型 (保持不变)
export interface ResponseDataType<T = any> {
  data: T;
  total?: number; // 这里的total是原始responseData.data.total
  code: number;
  message?: string;
  version?: string; // 根据你的后端格式添加
}

// 导出链接类型 (保持不变)
export interface ExportLinkType {
  link: string;
}

// 消息提示类型 (保持不变)
export interface MessageType {
  GET_DATA_IF_FAILED?: string;
  GET_DATA_IF_SUCCEED?: string;
  EXPORT_DATA_IF_FAILED?: string;
  EXPORT_DATA_IF_SUCCEED?: string;
}

// 列表返回类型 (保持不变，用于 transformFn 的返回值)
export interface ListReturn<T = any> {
  list: T[]; // 修改为 list 以匹配后端 data.list 结构
  total: number;
}

// OptionsType (微调，transformFn 的参数和返回值更明确)
export interface OptionsType<T = any, K = any> {
  // K 用于表示 filterOption 的类型
  requestError?: (error: any) => void; // 传递错误信息
  requestSuccess?: (result: ListReturn<T>) => void; // 传递成功数据
  exportError?: (error: any) => void;
  exportSuccess?: () => void;
  filterOption?: Ref<K>; // 使用泛型 K 表示筛选条件类型
  // transformFn 接收原始的 ResponseDataType<any>，返回 ListReturn<T>
  transformFn?: (res: ResponseDataType<any>) => ListReturn<T>;
  exportRequestFn?: (...args: any) => Promise<ResponseDataType<ExportLinkType>>;
  message?: MessageType;
  preRequest?: (...args: any[]) => void;
  immediate?: boolean;
  pageSizes?: number[];
}
